﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufItem.h"
#include "GnufDropdownMenuControl.h"

namespace gnuf {
    
    class Toolbar;
    class ButtonEx;
    class DropdownMenu;
    class DropdownMenuEntry;

    class GNUF_BASE_EXPORT DropdownMenuEntryList
    {
        CANNOT_COPY_OR_ASSIGN(DropdownMenuEntryList)
    public:
        DropdownMenuEntryList();
        virtual ~DropdownMenuEntryList();

    public:
        DropdownMenuEntry * addEntry();
        void addSeparator();
        DropdownMenu * addMenu();

        typedef std::list< gcmp::OwnerPtr<Item> > Contents;
        typedef std::vector< Item * > RawContents;
        inline const Contents & contents() const { return m_contents; }
        RawContents rawContents();

        int indexOf(const DropdownMenuEntry *) const;
        const DropdownMenuEntry * at(const int index) const;
        DropdownMenuEntry * at(const int index);
        void setCurrentIndex(const int index, const bool wantToDispatchEvent = true);
        inline int currentIndex() const { return m_currentIndex; }
        const DropdownMenuEntry * currentEntry() const;

        virtual Item * hostItem() = 0;
        virtual const Item * hostItem() const = 0;

        const gcmp::OwnerPtr< Info > & markInfo() const {
            return m_markInfo;
        }
        inline void setWantToMarkTheSelected(bool wantToMarkTheSelected) {
            m_wantToMarkTheSelected = wantToMarkTheSelected;
        }
        
        inline void setSupportMultiSelection(bool supportMultiSelection) {
            m_supportMultiSelection = supportMultiSelection;
        }

        inline bool wantToMarkTheSelected() const { return m_wantToMarkTheSelected; }
        inline bool supportMultiSelection()const { return m_supportMultiSelection; }
    private:
        DropdownMenuEntryList::Contents m_contents;
        int m_currentIndex;
        gcmp::OwnerPtr< Info > m_markInfo;
        bool m_wantToMarkTheSelected;
        bool m_supportMultiSelection;
    };
    
    class ContextMenu;
    class QtDropdownMenu;
    class GNUF_BASE_EXPORT DropdownMenu final 
        : public ItemWith<QtDropdownMenu>
        , public DropdownMenuControlAdpatation
        , public DropdownMenuEntryList
    {
        CANNOT_COPY_OR_ASSIGN(DropdownMenu)
        GNUF_WATCHABLE_OBJECT(DropdownMenu)
    public:
        static const EItemType Type;
        explicit DropdownMenu(ButtonEx *);
        explicit DropdownMenu(DropdownMenu *);
        explicit DropdownMenu(ContextMenu *);
        virtual ~DropdownMenu();

        void setCaption(const std::wstring & caption) {
            m_caption = caption;
        }
        inline const std::wstring & caption() const { return m_caption; }

        inline void setWantToSyncWithFakedButton(bool wantToSyncWithFakedButton) {
            m_wantToSyncWithFakedButton = wantToSyncWithFakedButton;
        }
        inline bool wantToSyncWithFakedButton() const { /*return m_wantToSyncWithFakedButton;*/return false; }

    protected:
        // Inherits from DropdownMenuList...
        virtual Item * hostItem() override { return this; }
        virtual const Item * hostItem() const override { return this; }

        // Inherits from ItemWith...
        virtual void onDisconnectFromMyQtItem() override;

        // Inherits from DropdownMenuControlAdpatation...
        virtual void onItemsVisibilityAndAbilityChanged(const std::vector<bool> &, const std::vector<bool> &) override;
        virtual void onVisibilityChanged(bool) override;
        virtual void onAbilityChanged(bool) override;
        virtual void onCollectLocation(std::set<const gcmp::UniqueString *> &) const override;
        virtual void onCurrentIndexChanged(int) override;
        virtual void onCheckStatusChanged(int, bool) override;
    private:
        std::wstring m_caption;
        bool m_wantToSyncWithFakedButton;
    };

    class QtContextMenu;
    class GNUF_BASE_EXPORT ContextMenu final
        : public ItemWith<QtContextMenu, RootItem>
        , public DropdownMenuEntryList
    {
        CANNOT_COPY_OR_ASSIGN(ContextMenu)
    public:
        static const EItemType Type;
        explicit ContextMenu(const gcmp::UniqueString * uniqueKey);
        virtual ~ContextMenu();

    public:
        void popup(int x, int y);

    protected:
        // Inherits from DropdownMenuList...
        virtual Item * hostItem() override { return this; }
        virtual const Item * hostItem() const override { return this; }

        // Inherits from ItemWith...
        virtual void onDisconnectFromMyQtItem() override;
    };
    
    class QtDropdownMenuActionWidget;
    class GNUF_BASE_EXPORT DropdownMenuEntry final : public ItemWith<QtDropdownMenuActionWidget, Item>
    {
        CANNOT_COPY_OR_ASSIGN(DropdownMenuEntry)
    public:
        static const EItemType Type;
        explicit DropdownMenuEntry(DropdownMenu *);
        explicit DropdownMenuEntry(ContextMenu *);
        virtual ~DropdownMenuEntry();
        int index() const;
        void setCaption(const std::wstring & caption) {
            m_caption = caption;
        }
        inline const std::wstring & caption() const { return m_caption; }
        inline bool getMenuEntryCheckState() { return m_bChecked; }
        inline void setMenuEntryCheckState(bool checkState){
            m_bChecked = checkState;
        }
        bool wantToMarkTheSelected() const;
        inline bool asSeparator() const { return m_asSeparator; }
        inline void setAsSeparator(bool asSepartor) {
            m_asSeparator = asSepartor;
        }
        inline bool asCheckBox() const { return m_asCheckBox; }
        inline void setAsCheckBox(bool asCheckBox) {
            m_asCheckBox = asCheckBox;
        }
    protected:
        // Inherits from ItemWith...
        virtual void onDisconnectFromMyQtItem() override;
        virtual void onPostVisibilityChanged() override;
        virtual void onPostAbilityChanged() override;
    private:
        std::wstring m_caption;
        bool m_asSeparator;
        bool m_bChecked;
        bool m_asCheckBox;
    };
}
